home *** CD-ROM | disk | FTP | other *** search
/ Gekkan Dennou Club 145 / Gekkan Dennou Club - 2000.6 Vol. 145 (Japan).7z / Gekkan Dennou Club - 2000.6 Vol. 145 (Japan) (Track 1).bin / tools / sharp / sxwork3.lzh / サンプル実用編 / チャート / CHDRAW.C < prev    next >
Text File  |  1994-03-10  |  19KB  |  644 lines

  1. /******************************************************************************
  2.  *    chdraw.c:    チャートの描画処理関数
  3.  ******************************************************************************
  4.  *    Workroom SX-68K Sample Program Copyright 1994 SHARP
  5.  */
  6. #include <stdio.h>
  7. #include <math.h>
  8. #include <sxgraph.h>        /* グラフ系マネージャを利用するときに必要 */
  9. #include <dialog.h>        /* ダイアログマンを利用するときに必要    */
  10. #include "chart.h"        /* このプログラム固有のヘッダファイル    */
  11.  
  12. static Rect rcoval = { 50, 50 + GRPY, 50 + 200, 50 + GRPY + 200 };
  13.  
  14. /******************************************************************************
  15.  *    drawCircle():    円グラフの描画
  16.  ******************************************************************************
  17.  *    引数:    ComVal *pcv    共通変数へのポインタ
  18.  */
  19. void drawCircle(ComVal *pcv)
  20. {
  21.     int i, r;            /* 円グラフの中心点    */
  22.     int oldpm, oldfc, oldbc, oldfm, oldff;
  23.     Point pt1, pt2;
  24.     Rect rc;            /* レクタングル        */
  25.     char str[32];            /* 文字列格納用        */
  26.  
  27.     static Rect OgiRect = { 0, 0, 40, 40 };
  28.  
  29.     /* 描画属性設定 */
  30.     oldpm = GMPenMode(G_PSET);
  31.     oldfc = GMForeColor(GC_BLACK);
  32.     oldbc = GMBackColor(GC_WHITE);
  33.     oldfm = GMFontMode(G_PSET);
  34.  
  35.     /* タイトル */
  36.     oldff = GMFontFace(G_BOLD | G_ULINE);
  37.     drawStrZ("円 グ ラ フ (単位:% )", LONGWORD(15, GRPY + 10));
  38.     GMFontFace(oldff);
  39.  
  40.     /* 総額表示 */
  41.     sprintf(str, "合  計  %8d 円\0", pcv->sum[pcv->month - 1]);
  42.     drawStrZ(str, LONGWORD(OGIX, GRPY + 10));
  43.  
  44.     /* 各項目名の表示 */
  45.     r = OgiRect.d.right / 2;
  46.     for (i = 0; i < 7; i++) {
  47.         rc = OgiRect;
  48.         GMSlideRect(&rc, LONGWORD(OGIX, i * 30 + 30 + GRPY));
  49.         GMForeColor(gColor[i]);
  50.         GMFillArc(&rc, CRCLSTR, CRCLEND);
  51.  
  52.         /* 扇型の縁取り */
  53.         GMForeColor(GC_BLACK);
  54.         GMFrameArc(&rc, CRCLSTR, CRCLEND);
  55.         pt1.p.x = (rc.d.right + rc.d.left) / 2 - 1;
  56.         pt1.p.y = (rc.d.bottom + rc.d.top) / 2 - 1;
  57.         pt2.x_y = angleToPos(CRCLSTR, r, r);
  58.         pt2.p.x += pt1.p.x;
  59.         pt2.p.y += pt1.p.y;
  60.         GMMove(pt2.x_y);
  61.         GMLine(pt1.x_y);
  62.         pt2.x_y = angleToPos(CRCLEND, r, r);
  63.         pt2.p.x += pt1.p.x;
  64.         pt2.p.y += pt1.p.y + 1;
  65.         GMLine(pt2.x_y);
  66.         drawStrZ(crclTtl[i], LONGWORD(OGIX + 55, rc.d.top + 4));
  67.     }
  68.     /* データ表示不能のとき */
  69.     if (pcv->sum[pcv->month - 1] == 0) {
  70.         GMForeColor(GC_BLACK);
  71.         /* 円弧描画レクタングル */
  72.         GMFrameOval(&rcoval);
  73.         GMPenMode(oldpm);
  74.         GMForeColor(oldfc);
  75.         GMBackColor(oldbc);
  76.         GMFontMode(oldfm);
  77.         return;
  78.     }
  79.     /* 円グラフを表示 */
  80.     drawArc(pcv);
  81.  
  82.     /* 描画属性をデフォルトの値にする */
  83.     GMPenMode(oldpm);
  84.     GMForeColor(oldfc);
  85.     GMBackColor(oldbc);
  86.     GMFontMode(oldfm);
  87. }
  88.  
  89. /******************************************************************************
  90.  *    drawArc():    円グラフの描画
  91.  ******************************************************************************
  92.  *    引数:    ComVal *pcv    共通変数へのポインタ
  93.  */
  94. void drawArc(ComVal *pcv)
  95. {
  96.     int i, scale, op;
  97.     int lastPM, lastFC, lastBC, lastFM;
  98.     int deg, dw, rx, ry;
  99.     int rate[7], drpt[2][7];
  100.     char str[16];
  101.     Point pt;
  102.  
  103.     calcRate(pcv, rate);
  104.  
  105.     /* 360度 / 金額合計 = 1円当たりの角度を求める */
  106.     scale = KETA1 * 360 / pcv->sum[pcv->month - 1];
  107.     op = 450;
  108.     for (i = 0; i < 7; i++) {
  109.         /* 描画終了角度 */
  110.         drpt[1][i] = op;
  111.         /* 描画開始角度 */
  112.         drpt[0][i] = op - ((pcv->money[pcv->month - 1][i] * scale + KETA1 / 2) / KETA1);
  113.         /* 次の描画開始位置のために待避 */
  114.         op = drpt[0][i];
  115.     }
  116.  
  117.     /* 描画属性設定 */
  118.     lastFC = GMForeColor(GC_WHITE);
  119.     lastBC = GMBackColor(GC_WHITE);
  120.     lastPM = GMPenMode(G_PSET);
  121.     lastFM = GMFontMode(G_PSET);
  122.  
  123.     /* 描画する */
  124.     for (i = 0; i < 7; i++)
  125.         /* startとendが同じ時は円を描いてしまうのでその場合は描画しない */
  126.         if (drpt[0][i] != drpt[1][i]) {
  127.             /* 扇型の描画 */
  128.             GMForeColor(gColor[i]);
  129.             GMFillArc(&rcoval, drpt[0][i], drpt[1][i]);
  130.         }
  131.     GMForeColor(GC_BLACK);
  132.     GMFrameOval(&rcoval);
  133.  
  134.     for (i = 0; i < 7; i++) {
  135.         dw = drpt[1][i] - drpt[0][i];
  136.         if (rate[i] != 0) {
  137.             /* 割合が0でない場合 */
  138.             deg = dw / 2 + drpt[0][i];
  139.             GMForeColor(GC_BLACK);
  140.             GMFontMode(G_PSET);
  141.             if (dw < 20) {
  142.                 /* 角度が20度以下の場合 */
  143.                 GMBackColor(GC_WHITE);
  144.                 rx = 18;
  145.                 ry = 12;
  146.             } else {
  147.                 /* 角度が20度以上の場合 */
  148.                 GMBackColor(gColor[i]);
  149.                 rx = -18;
  150.                 ry = -18;
  151.             }
  152.             /* 角度より円周上の位置を求める */
  153.             sprintf(str, "%.1f\0", (double) rate[i] / 10.0);
  154.             pt.x_y = angleToPos(deg, RADIUS + rx, RADIUS + ry);
  155.             pt.p.x += CENTERX;
  156.             pt.p.y += CENTERY;
  157.             /* (x,y)を中心に文字列を描画 */
  158.             drawStrM(str, pt.x_y);
  159.         }
  160.     }
  161.     GMForeColor(lastFC);
  162.     GMBackColor(lastBC);
  163.     GMPenMode(lastPM);
  164.     GMFontMode(lastFM);
  165. }
  166.  
  167. /******************************************************************************
  168.  *    calcRate():    指定月の各項目のパーセンテージを計算
  169.  ******************************************************************************
  170.  *    引数:    ComVal *pcv    共通変数へのポインタ
  171.  *        int *rate    パーセンテージの値を格納するポインタ
  172.  */
  173. void calcRate(ComVal *pcv, int *rate)
  174. {
  175.     int i, scale;
  176.  
  177.     /* 100.0% / 金額合計 = 1円当たりのパーセンテージを求める */
  178.     scale = KETA2 * 1000 / pcv->sum[pcv->month - 1];
  179.     for (i = 0; i < 7; i++)
  180.         rate[i] = (pcv->money[pcv->month - 1][i] * scale + KETA2 / 2) / KETA2;
  181. }
  182.  
  183. /******************************************************************************
  184.  *    angleToPos():    0~360度の値を円周上の座標に変換する
  185.  ******************************************************************************
  186.  *    引数:    int deg        角度(0~360)
  187.  *        int rx        円の半径(x)
  188.  *        int ry           〃   (y)
  189.  *    戻り値:    LPoint
  190.  */
  191. LPoint angleToPos(int deg, int rx, int ry)
  192. {
  193.     double dx, dy, rd;
  194.     Point pt;
  195.  
  196.     rd = (double) deg / (360.0 / (PI * 2.0));
  197.     dx = cos(rd) * rx;
  198.     dy = sin(rd) * ry;
  199.     /* 整数になおすため、四捨五入 */
  200.     pt.p.x =  (short)(dx + 0.5 * (dx / fabs(dx)));
  201.     pt.p.y = -(short)(dy + 0.5 * (dy / fabs(dy)));
  202.     return pt.x_y;
  203. }
  204.  
  205. /******************************************************************************
  206.  *    drawRadar():    レーダーチャートの描画
  207.  ******************************************************************************
  208.  *    引数:    ComVal *pcv    共通変数へのポインタ
  209.  */
  210. void drawRadar(ComVal *pcv)
  211. {
  212.     int oldpm, oldfc, oldfm, oldff;
  213.     int i, j;            /* ループカウンタ        */
  214.     int max;            /* 目盛りの最大値        */
  215.     int dMax;            /* データの最大値        */
  216.     int val[7];            /* 各パラメータの大きさ(比)    */
  217.     int temp;            /* ワーク            */
  218.     int len;            /* 目盛り線の長さ        */
  219.     double ang;            /* 分割角度            */
  220.     double th;            /* 回転角度            */
  221.     double vx[7], vy[7];        /* レーダーチャート各軸のベクトル */
  222.     double nx, ny;            /* 軸の法線ベクトル        */
  223.     char str[32];            /* 表示文字列格納用        */
  224.     Point pt, pt2, vpt[7];
  225.     LPoint oldlps;
  226.  
  227.     /* データの最大値をdMaxとする */
  228.     dMax = 0;
  229.     for (i = 0; i < 7; i++) {
  230.         temp = pcv->money[pcv->month - 1][i];
  231.         if (dMax < temp)
  232.             dMax = temp;
  233.     }
  234.  
  235.     /* 目盛りの最大値の計算 */
  236.     for (max = 10; ; max *= 10)
  237.         /* 除算の結果が1桁になるまで */
  238.         if (dMax / max < 10)
  239.             break;
  240.     /* 目盛りの最大値は5刻みの値にする */
  241.     for (i = 5; i <= 10; i += 5) {
  242.         temp = i * max;
  243.         /* 除算の結果が0 */
  244.         if (dMax / temp == 0) {
  245.             max = temp;
  246.             break;
  247.         }
  248.     }
  249.  
  250.     /* 各データがmaxの何パーセントか計算する */
  251.     /* (小数点以下四捨五入) */
  252.     for (i = 0; i < 7; i++)
  253.         val[i] = (int)(100.0 * ((double) pcv->money[pcv->month - 1][i] / (double) max) + 0.5);
  254.  
  255.     /* 各軸のベクトルの計算 */
  256.     ang = 0.897597901;        /* 360/7度をradianに変換したもの */
  257.     for (i = 0; i < 7; i++) {
  258.         /* 回転角 */
  259.         th = ang * (double) i;
  260.         /* ang(rad)づつ回転(cw) */
  261.         vx[i] = sin(th);
  262.         vy[i] = -cos(th);
  263.     }
  264.  
  265.     /* 描画属性設定 */
  266.     oldpm = GMPenMode(G_PSET);
  267.     oldfc = GMForeColor(GC_BLACK);
  268.     oldfm = GMFontMode(G_PSET);
  269.  
  270.     /* タイトル */
  271.     oldff = GMFontFace(G_BOLD | G_ULINE);
  272.     drawStrZ("レ ー ダ ー チ ャ ー ト (単位:円)", LONGWORD(15, GRPY + 10));
  273.     GMFontFace(oldff);
  274.     /* 総額表示 */
  275.     sprintf(str, "合  計  %8d 円\0", pcv->sum[pcv->month - 1]);
  276.     drawStrZ(str, LONGWORD(270, GRPY + 10));
  277.  
  278.     /* レーダーチャートの軸線7本の描画 */
  279.     for (i = 0; i < 7; i++) {
  280.         vpt[i].p.x = (int)(100.0 * vx[i]) + RADERSTX;
  281.         vpt[i].p.y = (int)(100.0 * vy[i]) + RADERSTY;
  282.         GMMove(LONGWORD(RADERSTX, RADERSTY)); /* ペンを移動する    */
  283.         GMLine(LONGWORD(vpt[i].p.x, vpt[i].p.y)); /* 直線を描画する */
  284.         /* 軸ベクトルの法線ベクトル */
  285.         nx = vy[i];
  286.         ny = -vx[i];
  287.         /* 目盛りの描画 */
  288.         for (j = 1; j < 11; j++) {
  289.             /* 5の倍数の目盛りは長さ5/その他は2 */
  290.             len = (j == 5 || j == 10) ? 5 : 2;
  291.             /* ペンを移動する */
  292.             GMMove(LONGWORD(RADERSTX + (int)(10 * j * vx[i] + len * nx), RADERSTY + (int)(10 * j * vy[i] + len * ny)));
  293.             /* 直線を描画する */
  294.             GMLine(LONGWORD(RADERSTX + (int)(10 * j * vx[i] - len * nx), RADERSTY + (int)(10 * j * vy[i] - len * ny)));
  295.         }
  296.     }
  297.     /* 項目 */
  298.     drawStrZ("住居", LONGWORD(RADERSTX - 12, RADERSTY - 120));
  299.     vpt[1].p.x += 12;
  300.     vpt[1].p.y -= 12;
  301.     drawStrZ("光熱・水道", vpt[1].x_y);
  302.     vpt[2].p.x += 12;
  303.     drawStrZ("食物", vpt[2].x_y);
  304.     vpt[3].p.x -= 12;
  305.     vpt[3].p.y += 6;
  306.     drawStrZ("被服", vpt[3].x_y);
  307.     vpt[4].p.x -= 18;
  308.     vpt[4].p.y += 6;
  309.     drawStrZ("貯蓄", vpt[4].x_y);
  310.     vpt[5].p.x -= 72;
  311.     drawStrZ("教養・娯楽", vpt[5].x_y);
  312.     vpt[6].p.x -= 36;
  313.     vpt[6].p.y -= 12;
  314.     drawStrZ("雑費", vpt[6].x_y);
  315.  
  316.     /* WARNING : dMax が0だったら */
  317.     if (dMax == 0)
  318.         return;
  319.  
  320.     /* データの描画 */
  321.     /* 1番目のデータを始点とする */
  322.     pt.p.x = (int)(val[0] * vx[0]) + RADERSTX;
  323.     pt.p.y = (int)(val[0] * vy[0]) + RADERSTY;
  324.     GMMove(pt.x_y);
  325.     /* 一周する */
  326.     oldlps = GMPenSize(LONGWORD(2, 2));
  327.     GMForeColor(GC_RED);
  328.     for (i = 1; i < 7; i++) {
  329.         pt2.p.x = (int)(val[i] * vx[i]) + RADERSTX;
  330.         pt2.p.y = (int)(val[i] * vy[i]) + RADERSTY;
  331.         GMLine(pt2.x_y);
  332.     }
  333.     /* 最後は始点につけて閉じる */
  334.     GMLine(pt.x_y);
  335.     GMPenSize(oldlps);
  336.  
  337.     /* 目盛りの値を入れる */
  338.     /* max/2 */
  339.     GMForeColor(GC_BLACK);
  340.     sprintf(str, "%8d\0", max / 2);
  341.     drawStrZ(str, LONGWORD(RADERSTX - 54, RADERSTY - 10 * 5 - 6));
  342.     /* max */
  343.     sprintf(str, "%8d\0", max);
  344.     drawStrZ(str, LONGWORD(RADERSTX - 54, RADERSTY - 10 * 10 - 6));
  345.  
  346.     /* 描画属性をデフォルトの値にする */
  347.     GMPenMode(oldpm);
  348.     GMForeColor(oldfc);
  349.     GMFontMode(oldfm);
  350. }
  351.  
  352. /******************************************************************************
  353.  *    drawBar():    棒グラフの描画
  354.  ******************************************************************************
  355.  *    引数:    ComVal *pcv    共通変数へのポインタ
  356.  */
  357. void drawBar(ComVal *pcv)
  358. {
  359.     int i, j;            /* ループカウンタ    */
  360.     int kt, mt, st;
  361.     int len, keta, dot, measmax, meas, dMax;
  362.     int oldpm, oldfc, oldfm, oldff;
  363.     int mon[4];
  364.     Point pt;
  365.     Rect rc;            /* レクタングル        */
  366.     char str[32];            /* 表示文字列用        */
  367.  
  368.     /* 表示する月を設定 */
  369.     mon[3] = pcv->month;        /* 今月        */
  370.     mon[2] = lastMonth(mon[3]);    /* 1ヶ月前    */
  371.     mon[1] = lastMonth(mon[2]);    /* 2ヶ月前    */
  372.     mon[0] = lastMonth(mon[1]);    /* 3ヶ月前    */
  373.  
  374.     /* 描画属性設定 */
  375.     oldpm = GMPenMode(G_PSET);
  376.     oldfc = GMForeColor(GC_BLACK);
  377.     oldfm = GMFontMode(G_PSET);
  378.  
  379.     /* タイトル */
  380.     oldff = GMFontFace(G_BOLD | G_ULINE);
  381.     drawStrZ("棒 グ ラ フ (単位:円)", LONGWORD(15, GRPY + 10));
  382.     GMFontFace(oldff);
  383.     /* 総額表示 */
  384.     sprintf(str, "合  計  %8d 円\0", pcv->sum[pcv->month - 1]);
  385.     drawStrZ(str, LONGWORD(270, GRPY + 10));
  386.  
  387.     /* 横軸、縦軸を描画 */
  388.     GMMove(LONGWORD(BARSTX, BARSTY)); /* ペンを移動する        */
  389.     GMLine(LONGWORD(BARSTX + BARLEN + 20, BARSTY)); /* 直線を描画する */
  390.     GMMove(LONGWORD(BARSTX, BARSTY)); /* ペンを移動する        */
  391.     GMLine(LONGWORD(BARSTX, BARSTY + 160)); /* 直線を描画する    */
  392.  
  393.     /* データの最大値dMaxを求める */
  394.     /* 今月 */
  395.     dMax = 0;
  396.     for (i = 0; i < 4; i++)
  397.         if (dMax < pcv->sum[mon[i] - 1])
  398.             dMax = pcv->sum[mon[i] - 1];
  399.  
  400.     /* 最大値の桁数を求める(桁数を文字数でカウント) */
  401.     kt = sprintf(str, "%d", dMax);
  402.     keta = (int) pow(10.0, (double)(kt - 1));    /* 10^kt */
  403.     /* 目盛りの最大値 */
  404.     measmax = ((dMax / keta) + 1) * keta;
  405.     meas = keta / 10;
  406.     /* 1円当たりのドット数を求める */
  407.     dot = (BARSCL * BARLEN) / measmax;
  408.  
  409.     /* 最大値の桁数が1桁の場合 */
  410.     if (kt == 1) {
  411.         kt = 2;
  412.         measmax = 10;
  413.         meas = 1;
  414.         dot = (BARSCL * BARLEN) / measmax;
  415.     }
  416.     /* 目盛り上の数値の単位を調整 */
  417.     if (kt > 2) {
  418.         mt = 2;
  419.         st = kt - mt - 1;
  420.     } else {
  421.         st = 0;
  422.         mt = kt - 1;
  423.     }
  424.     /* 目盛りと、単位の表示 */
  425.     for (i = 0; i <= measmax / meas; i++) {
  426.         if ((i % 5) == 0)
  427.             /* 目盛りの番号が5/10進むごとに */
  428.             len = ((i % 10) != 0) ? 3 : 5;
  429.         else
  430.             /* 目盛りの分割数が30以下/その他の目盛り番号の場合 */
  431.             len = (measmax / meas <= 30) ? 2 : 0;
  432.         /* 目盛りの描画と数値の表示 */
  433.         j = (dot * meas * i + BARSCL / 2) / BARSCL;
  434.         if (len == 5) {
  435.             sprintf(str, "%d\0", i * (int) pow(10.0, (double)(mt - 1)));
  436.             drawStrM(str, LONGWORD(BARSTX + j, BARSTY - len - 6));
  437.         }
  438.         GMMove(LONGWORD(BARSTX + j, BARSTY + len)); /* ペンを移動する */
  439.         GMLine(LONGWORD(BARSTX + j, BARSTY - len)); /* 直線を描画する */
  440.     }
  441.     /* 3桁以上の数値の場合 */
  442.     if (st != 0) {
  443.         /* 目盛りの数値のスケール表示 */
  444.         sprintf(str, "(x%d)\0", (int) pow(10.0, (double) st));
  445.         drawStrZ(str, LONGWORD(BARSTX + BARLEN + 18, BARSTY - 11));
  446.     }
  447.     /* 月の表示 */
  448.     for (j = 0; j < 4; j++) {
  449.         sprintf(str, "%2d月\0", mon[j]);
  450.         drawStrZ(str, LONGWORD(BARSTX - 24 - 3, BARSTY + 14 + j * BAROFF));
  451.     }
  452.     /* 棒グラフの描画 */
  453.     for (j = 0; j < 4; j++) {
  454.         rc.d.right = BARSTX;
  455.         rc.d.top = BARSTY + 8 + j * BAROFF;
  456.         for (i = 0; i < 7; i++) {
  457.             rc.d.left = rc.d.right;
  458.             rc.d.right = rc.d.left + (dot * pcv->money[mon[j] - 1][i] + BARSCL / 2) / BARSCL;
  459.             rc.d.bottom = rc.d.top + 25;
  460.             GMForeColor(gColor[i]);
  461.             GMFillRect(&rc);
  462.             GMForeColor(GC_BLACK);
  463.             rc.d.right++;
  464.             /* 縁取りの描画 */
  465.             GMFrameRect(&rc);
  466.             rc.d.right--;
  467.         }
  468.     }
  469.     GMForeColor(GC_BLACK);
  470.     /* 総額表示 */
  471.     for (j = 0; j < 4; j++) {
  472.         sprintf(str, "%8d 円\0", pcv->sum[mon[j] - 1]);
  473.         drawStrZ(str, LONGWORD(BARGX, BARSTY + 14 + j * BAROFF));
  474.     }
  475.  
  476.     /* 項目名表示 */
  477.     /* 棒グラフに対応した色の付いたレクタングルと文字で表す */
  478.     for (i = 0; i < 7; i++) {
  479.         rc.d.left = BARTX + (i / 2) * 90;
  480.         rc.d.top = BARTY + (i % 2) * 20;
  481.         rc.d.right = rc.d.left + 10;
  482.         rc.d.bottom = rc.d.top + 10;
  483.         GMForeColor(gColor[i]);
  484.         GMFillRect(&rc);
  485.         GMForeColor(GC_BLACK);
  486.         GMFrameRect(&rc);
  487.         pt.p.x = rc.d.left + 10 + 5;
  488.         pt.p.y = rc.d.top;
  489.         drawStrZ(crclTtl[i], pt.x_y);
  490.     }
  491.     /* 描画属性をデフォルトの値にもどす */
  492.     GMPenMode(oldpm);
  493.     GMForeColor(oldfc);
  494.     GMFontMode(oldfm);
  495. }
  496.  
  497. /******************************************************************************
  498.  *    drawLine():    折れ線グラフの描画
  499.  ******************************************************************************
  500.  *    引数:    ComVal *pcv    共通変数へのポインタ
  501.  */
  502. void drawLine(ComVal *pcv)
  503. {
  504.     int len, i, j;
  505.     int oldpm, oldfc, oldfm, oldff;
  506.     int mt, st;
  507.     int kt, keta, dot, measmax, meas, dMax;
  508.     int mon[4];
  509.     Point pt;
  510.     LPoint oldlps;
  511.     Rect rc;
  512.     char str[32];
  513.  
  514.     /* 月 */
  515.     mon[3] = pcv->month;
  516.     mon[2] = lastMonth(mon[3]);
  517.     mon[1] = lastMonth(mon[2]);
  518.     mon[0] = lastMonth(mon[1]);
  519.  
  520.     /* データの最大値dMaxを求める */
  521.     dMax = 0;
  522.     for (j = 0; j < 4; j++)
  523.         for (i = 0; i < 7; i++)
  524.             if (dMax < pcv->money[mon[j] - 1][i])
  525.                 dMax = pcv->money[mon[j] - 1][i];
  526.  
  527.     /* 最大値の桁数を求める(桁数を文字数でカウント) */
  528.     kt = sprintf(str, "%d", dMax);
  529.     keta = pow(10.0, (double)(kt - 1)); /* 10^kt */
  530.     /* 目盛りの最大値 */
  531.     measmax = ((dMax / keta) + 1) * keta;
  532.     meas = keta / 10;
  533.     /* 1円当たりのドット数を求める */
  534.     dot = (LINESCL * LINEVL) / measmax;
  535.  
  536.     /* 最大値の桁数が1桁の場合 */
  537.     if (kt == 1) {
  538.         kt = 2;
  539.         measmax = 10;
  540.         meas = 1;
  541.         dot = (LINESCL * LINEVL) / measmax;
  542.     }
  543.     /* 目盛り上の数値の単位を調整 */
  544.     if (kt > 2) {
  545.         mt = 2;
  546.         st = kt - mt - 1;
  547.     } else {
  548.         st = 0;
  549.         mt = kt - 1;
  550.     }
  551.  
  552.     /* 描画属性設定 */
  553.     oldpm = GMPenMode(G_PSET);
  554.     oldfc = GMForeColor(GC_BLACK);
  555.     oldfm = GMFontMode(G_PSET);
  556.     /* タイトル */
  557.     oldff = GMFontFace(G_BOLD | G_ULINE);
  558.     drawStrZ("折 れ 線 グ ラ フ (単位:円)", LONGWORD(15, GRPY + 10));
  559.     GMFontFace(oldff);
  560.     /* 総額表示 */
  561.     sprintf(str, "合  計  %8d 円\0", pcv->sum[pcv->month - 1]);
  562.     drawStrZ(str, LONGWORD(270, GRPY + 10));
  563.  
  564.     /* 項目名表示 */
  565.     /* 折れ線グラフに対応した色の付いた線と文字で表す */
  566.     for (i = 0; i < 7; i++) {
  567.         rc.d.left = LINETX + (i / 2) * 90;
  568.         rc.d.top = LINETY + (i % 2) * 15 + 5;
  569.         rc.d.right = rc.d.left + 10;
  570.         rc.d.bottom = rc.d.top + 3;
  571.         GMForeColor(gColor[i]);
  572.         GMFillRect(&rc);
  573.         GMForeColor(GC_BLACK);
  574.         pt.p.x = rc.d.left + 15;
  575.         pt.p.y = rc.d.top - 5;
  576.         drawStrZ(crclTtl[i], pt.x_y);
  577.     }
  578.     /* 目盛り軸 */
  579.     GMForeColor(GC_BLACK);
  580.     /* 縦軸、横軸を表示 */
  581.     /* 横軸は5ドットだけ下にずらす(データで0を見易いように) */
  582.     GMMove(LONGWORD(LINESTX, LINESTY + 5)); /* ペンを移動する    */
  583.     GMLine(LONGWORD(LINESTX + LINEHL, LINESTY + 5)); /* 直線を描画する */
  584.     GMMove(LONGWORD(LINESTX, LINESTY + 5)); /* ペンを移動する    */
  585.     GMLine(LONGWORD(LINESTX, LINESTY - LINEVL - 5)); /* 直線を描画する */
  586.  
  587.     /* 金額の目盛りと、単位の表示 */
  588.     for (i = 0; i <= measmax / meas; i++) {
  589.         if ((i % 5) == 0)
  590.             /* 目盛りの番号が5/10進むごとに */
  591.             len = ((i % 10) != 0) ? 3 : 5;
  592.         else
  593.             /* 目盛りの分割数が30以下/その他の目盛り番号の場合 */
  594.             len = (measmax / meas <= 30) ? 2 : 0;
  595.         /* 目盛りの描画と数値の表示 */
  596.         j = (dot * meas * i + LINESCL / 2) / LINESCL;
  597.         if (len == 5) {
  598.             sprintf(str, "%4d\0", i * (int) pow(10.0, (double)(mt - 1)));
  599.             drawStrZ(str, LONGWORD(LINESTX - 5 - 26, LINESTY - j - 6));
  600.         }
  601.         /* ペンを移動する */
  602.         GMMove(LONGWORD(LINESTX - len, LINESTY - j));
  603.         /* 直線を描画する */
  604.         GMLine(LONGWORD(LINESTX + len, LINESTY - j));
  605.     }
  606.     /* 3桁以上の数値の場合 */
  607.     if (st != 0) {
  608.         /* 目盛りの数値のスケール表示 */
  609.         j = sprintf(str, "(x%d)\0", (int) pow(10.0, (double) st));
  610.         drawStrZ(str, LONGWORD(LINESTX - j * 6 - 2, LINESTY - LINEVL - 18));
  611.     }
  612.  
  613.     /* 月表示 */
  614.     for (j = 0; j < 4; j++) {
  615.         /* ペンを移動する */
  616.         GMMove(LONGWORD(LINESTX + 30 + j * LINEOFF, LINESTY));
  617.         /* 直線を描画する */
  618.         GMLine(LONGWORD(LINESTX + 30 + j * LINEOFF, LINESTY + 5 + 5));
  619.         sprintf(str, "%2d月\0", mon[j]);
  620.         drawStrZ(str, LONGWORD(LINESTX + 30 + j * LINEOFF - 12, LINESTY + 5 + 5 - 2));
  621.     }
  622.  
  623.     /* 折れ線グラフの描画 */
  624.     oldlps = GMPenSize(LONGWORD(2, 2));
  625.     for (i = 0; i < 7; i++) {
  626.         GMForeColor(gColor[i]);
  627.         pt.p.x = LINESTX + 30;
  628.         for (j = 0; j < 4; j++) {
  629.             pt.p.y = LINESTY - (dot * pcv->money[mon[j] - 1][i] + LINESCL / 2) / LINESCL;
  630.             if (j == 0)
  631.                 GMMove(pt.x_y);
  632.             else
  633.                 GMLine(pt.x_y);
  634.             pt.p.x += 75;
  635.         }
  636.     }
  637.     GMPenSize(oldlps);
  638.  
  639.     /* 描画属性をデフォルトの値に戻す */
  640.     GMPenMode(oldpm);
  641.     GMForeColor(oldfc);
  642.     GMFontMode(oldfm);
  643. }
  644.